package org.linlinjava.litemall.web.service;

import static org.linlinjava.litemall.web.util.WebResponseCode.ORDER_PAY_IS_NULL_MERMEBR;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.core.exception.EncryptionException;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.ResponseUtil.Response;
import org.linlinjava.litemall.core.util.paymentCodeUtil.EncryptionUtils;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.web.vo.MemberQueryResponseVO;
import org.linlinjava.litemall.web.vo.WebGiftCardUserVO;
import org.linlinjava.litemall.web.vo.WebMyCouponsVO;
import org.linlinjava.litemall.web.vo.WebPayMemberUserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 会员服务
 */
@Service
@RequiredArgsConstructor
public class WebMemberService {

    private final LitemallUserService userService;
    private final LumierelLevelMemberService lumierelLevelMemberService;
    private final CouponVerifyService couponVerifyService;
    private final LumiereCouponUserService lumiereCouponUserService;
    private final LumiereCouponStrategyService lumiereCouponStrategyService;
    private final LumiereCouponService lumiereCouponService;
    private final LitemallGiftCardUserService litemallGiftCardUserService;
    private final LumierePayMemberUserService lumierePayMemberUserService;
    private final LumierePayMemberService lumierePayMemberService;
    private final LitemallShopRegionService shopRegionService;
    private final LitemallRegionService regionService;
    /**
     * 查询会员信息
     *
     * @param condition
     * @return
     */
    @Transactional
    public Response<MemberQueryResponseVO> query(String condition,Integer shopId) {
        if (!StringUtils.isNotBlank(condition)) {
            return ResponseUtil.badArgument();
        }
        try {
            condition = EncryptionUtils.decrypt(condition);
        } catch (EncryptionException e) {
            return ResponseUtil.fail(814, "付款码已过期，请刷新再试");
        } catch (Exception e) {
            return ResponseUtil.fail(815, "付款码有误解析失败");
        }
        List<LitemallUser> result = userService.queryByCondition(condition);
        if (CollectionUtils.isEmpty(result)) {
            return ResponseUtil.badArgument(ORDER_PAY_IS_NULL_MERMEBR, "会员不存在");
        }
        LitemallUser user = result.get(0);
        List<LumierePayMemberUser> payMemberUsers = lumierePayMemberUserService.listMemberByUserId(user.getId());
        //会员的倍率
        Integer cityRegionId = getShopRegionId(shopId);
        //计算最高优惠率
        BigDecimal memberPer = new BigDecimal(0);
        Boolean notOverlay = false;
        BigDecimal maxMemberPer = new BigDecimal(0);
        //叠加付费会员优惠比例
        if(!payMemberUsers.isEmpty()){
            for(LumierePayMemberUser payMemberUser : payMemberUsers){
                if(payMemberUser.getEndTime().isBefore(LocalDateTime.now())){
                    continue;
                }
                //获得付费会员
                LumierePayMember payMember = lumierePayMemberService.findById(payMemberUser.getPayMemberId());
                //判断可以在该店使用
                Boolean isUse = payMember.getShopIds()!=null? ArrayUtil.contains(payMember.getShopIds(), cityRegionId):true;
                //当付费会员允许 汇率叠加
                if(payMember.getIsOverlay()==1 && isUse &&payMember.getDicountPer() != null){
                    memberPer=memberPer.add((payMember.getDicountPer().divide(new BigDecimal(100)))).setScale(2, BigDecimal.ROUND_HALF_UP);
                    notOverlay=true;
                }
                //选择一个最高的会员优惠率
                if(payMember.getDicountPer()!=null&&(memberPer.compareTo(payMember.getDicountPer())==-1)){
                    maxMemberPer=payMember.getDicountPer();
                }
            }
            //如果没有一个会员叠加，则选择一个最高的会员优惠率
            memberPer=notOverlay==false?maxMemberPer.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP):memberPer;
        }
        MemberQueryResponseVO response = new MemberQueryResponseVO();
        BeanUtils.copyProperties(result.get(0), response);
        //查询等级会员名称
        LumiereLevelMember levelMember = lumierelLevelMemberService.findById(response.getUserLevel().intValue());
        response.setLevelMember(ObjectUtil.isNotNull(levelMember) ? levelMember.getName() : "No membership level");
        response.setMembershipNumber(result.get(0).getMembershipNumber());
        response.setMaxMemberPer(memberPer.doubleValue());
        return ResponseUtil.ok(response);
    }

    /**
     * 获取店铺的地区id
     * @param shopId
     */
    private Integer getShopRegionId(Integer shopId) {
        List<LitemallShopRegion> litemallShopRegions = shopRegionService.queryByShopId(shopId);
        if(!CollectionUtils.isEmpty(litemallShopRegions)) {
            for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
                LitemallRegion litemallRegion = regionService.findById(litemallShopRegion.getRegionId());
                if(Constants.REGION_TYPE_CITY == litemallRegion.getType()) {
                    return litemallShopRegion.getRegionId();
                }
            }
        }
        return null;
    }
    public Response queryCoupons(String membershipNumber, Integer limit, Integer page, Integer shopId, List<Integer> goodsIds) {
        LitemallUser user = userService.queryByCondition(membershipNumber).get(0);
        //PageHelper.startPage(page, limit);
        List<LumiereCouponUser> lumiereCouponUsers = couponVerifyService.checkCouponStrategy(lumiereCouponUserService.list(Wrappers.lambdaQuery(LumiereCouponUser.class)
                .eq(LumiereCouponUser::getUserId, user.getId()).orderByDesc(LumiereCouponUser::getAddTime)), new BigDecimal(100000),2,shopId,goodsIds);
        //PageInfo pageInfo = new PageInfo<>(lumiereCouponUsers);
        List<WebMyCouponsVO> webMyCouponsVOS = lumiereCouponUsers.stream().map(lumiereCouponUser -> {
            LumiereCouponStrategy couponStrategy = lumiereCouponStrategyService.findByid(lumiereCouponUser.getStrategyId());
            LumiereCoupon coupon = lumiereCouponService.getById(lumiereCouponUser.getCouponId());
            WebMyCouponsVO webMyCouponsVO = WebMyCouponsVO.builder()
                    .couponName(couponStrategy.getName())
                    .couponType(couponStrategy.getCouponType())
                    .pictureUrl(coupon.getPictureUrl())
                    .descr(coupon.getDescr())
                    .startTime(lumiereCouponUser.getStartTime())
                    .endTime(lumiereCouponUser.getEndTime())
                    .ranges(couponStrategy.getRanges())
                    .discountType(couponStrategy.getDiscountType())
                    .discountRate(couponStrategy.getDiscountRate())
                    .discount(couponStrategy.getDiscount())
                    .min(couponStrategy.getMin())
                    .useLimit(couponStrategy.getUseLimitNum())
                    .useLimitNum(couponStrategy.getUseLimitNum())
                    .useInstruction(couponStrategy.getUseInstruction())
                    .code(lumiereCouponUser.getCode())
                    .addTime(lumiereCouponUser.getAddTime())
                    .build();
            return webMyCouponsVO;
        }).collect(Collectors.toList());
        //pageInfo.setList(webMyCouponsVOS);
		/*List<WebMyCouponsVO> wxMyCouponsVOS = lumiereCouponUserService.selectJoinList(WebMyCouponsVO.class, new MPJLambdaWrapper<LumiereCouponUser>()
				.selectAs(LumiereCoupon::getName, WebMyCouponsVO::getCouponName)
				.selectAs(LumiereCouponStrategy::getRanges, WebMyCouponsVO::getRanges)
				.select(LumiereCoupon::getDescr,LumiereCoupon::getPictureUrl)
				.select(LumiereCouponUser::getStartTime, LumiereCouponUser::getEndTime, LumiereCouponUser::getCode, LumiereCouponUser::getAddTime)
				.select(LumiereCouponStrategy::getDiscountType,
						LumiereCouponStrategy::getDiscountRate,
						LumiereCouponStrategy::getDiscount,
						LumiereCouponStrategy::getMin,
						LumiereCouponStrategy::getUseLimit,
						LumiereCouponStrategy::getUseLimitNum,
						LumiereCouponStrategy::getUseInstruction,
						LumiereCouponStrategy::getCouponType)
				.isNull(LumiereCouponUser::getUsedTime)
				.gt(LumiereCouponUser::getEndTime, LocalDateTime.now())
				.eq(LumiereCouponUser::getUserId,userId)
				.leftJoin(LumiereCoupon.class, LumiereCoupon::getId, LumiereCouponUser::getCouponId)
				.leftJoin(LumiereCouponStrategy.class, LumiereCouponStrategy::getId, LumiereCouponUser::getStrategyId)
				.orderByDesc(LumiereCouponUser::getAddTime)
		);*/
        return ResponseUtil.okList(webMyCouponsVOS);
    }

    public Response queryGifts(String membershipNumber) {
        LitemallUser user = userService.queryByCondition(membershipNumber).get(0);
        List<WebGiftCardUserVO> webGiftCardUserVOS = litemallGiftCardUserService.selectJoinList(WebGiftCardUserVO.class, new MPJLambdaWrapper<LitemallGiftCardUser>()
                .selectAll(LitemallGiftCardUser.class)
                .selectAs(LitemallGiftCard::getName, WebGiftCardUserVO::getGiftName)
                .select(LitemallGiftCard::getPicUrl)
                .eq(LitemallGiftCardUser::getUserId, user.getId())
                .leftJoin(LitemallGiftCard.class, LitemallGiftCard::getId, LitemallGiftCardUser::getGiftCardId)
                .orderByDesc(LitemallGiftCardUser::getAddTime)
        );
        return ResponseUtil.ok(webGiftCardUserVOS);
    }

    public Response queryPayMember(String membershipNumber, Integer shopId) {
        LitemallUser user = userService.queryByCondition(membershipNumber).get(0);
        List<WebPayMemberUserVO> memberUserVOS = lumierePayMemberUserService.list(Wrappers.lambdaQuery(LumierePayMemberUser.class)
                .eq(LumierePayMemberUser::getUserId, user.getId())
                .gt(LumierePayMemberUser::getEndTime,LocalDateTime.now())
                .eq(LumierePayMemberUser::getDeleted, 0)
                .orderByDesc(LumierePayMemberUser::getAddTime)).stream().map(payMemberUser -> {
            LumierePayMember payMember = lumierePayMemberService.findById(payMemberUser.getPayMemberId());
            WebPayMemberUserVO payMemberUserVO = WebPayMemberUserVO.builder()
                    .payMemberName(payMember.getName())
                    .picUrl(payMember.getPicUrl())
                    .dicountPer(payMember.getDicountPer()==null?new BigDecimal(0.00):payMember.getDicountPer())
                    .isOverlay(payMember.getIsOverlay())
                    .buyTimes(payMember.getBuyTimes())
                    .useRange(payMember.getUseRange())
                    .money(payMember.getMoney())
                    .point(payMember.getPoint())
                    .shopIds(payMember.getShopIds())
                    .isSupportReneval(payMember.getIsSupportReneval())
                    .renevalMoney(payMember.getRenevalMoney())
                    .renevalPoint(payMember.getRenevalPoint())
                    .pointRatio(payMember.getPointRatio())
                    .paymentInstructions(payMember.getPaymentInstructions())
                    .build();
            BeanUtils.copyProperties(payMemberUser, payMemberUserVO);
            return payMemberUserVO;
        }).filter(l-> l.getShopIds()==null||Arrays.asList(l.getShopIds()).contains(shopId)).collect(Collectors.toList());
        return ResponseUtil.ok(memberUserVOS);
    }
}
